﻿using System;
using System.Collections;
using ProjectDanmaku.Avatar.Basic;
using ProjectDanmaku.Entity;
using ProjectDanmaku.Entity.Rendering;
using ProjectDanmaku.Scenario;
using ProjectDanmaku.UI;
using ProjectDanmaku.Util;
using UnityEngine;

namespace ProjectDanmaku.Avatar.Reimu
{
    public class ReimuController : AvatarBehavior
    {
        private enum State
        {
            Human, Monster
        }

        [SerializeField] private bool godMode = false;
        [SerializeField] private float godTime = 1f;
        [SerializeField] private float bulletAngle = 7f;
        [SerializeField] private float fireInterval = 0.08f;
        
        private ReimuCardBulletLayer _reimuCardBulletLayer;
        private ReimuHomingCardBulletLayer _reimuHomingCardBuletEntityData;
        
        private float _lastFireTime;

        [SerializeField] private float initPower;
        [SerializeField] private Vector2 bulletSpeed;
        [SerializeField] private GameObject collidePoint;
        [SerializeField] private GameObject deadRingPrefab;
        [SerializeField] private SpriteProgressBar powerProgressPar;

        [SerializeField] private AudioSource soundSource;
        
        [SerializeField] private AudioClip cardEmitSound;
        [SerializeField] private AudioClip deathSound;

        private float power;

        private State _state = State.Human;
        private bool _isDead = false;

        private float _lastDeathTime = -100;
        
        protected override void Awake()
        {
            base.Awake();

            _reimuCardBulletLayer = GetComponentInChildren<ReimuCardBulletLayer>();
            _reimuHomingCardBuletEntityData = GetComponentInChildren<ReimuHomingCardBulletLayer>();
            
            _lastFireTime = -100f;
        }

        protected override void Start()
        {
            power = initPower;
            
            base.Start();
            
            collidePoint.SetActive(Application.isMobilePlatform);
        }

        private void FixedUpdate()
        {
            power = Mathf.Min(power + 0.1f, 100);
            powerProgressPar.SetProgress(power / 100f);
        }

        public override void Movement(Vector2 movement)
        {
            if (_state == State.Monster)
            {
                movement *= 0.5f;
            }
            else
            {
                movement *= 2f;
            }
            base.Movement(movement);
        }

        private void Power20Emit(Vector2 posVec2)
        {
            _reimuCardBulletLayer.AddEntity(new ReimuCardEntityData()
            {
                Position = posVec2 + Vector2.up * 0.4f,
                Velocity = bulletSpeed,
                RotateZ = 90 * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.6f),
            });
        }

        private void Power60Emit(Vector2 posVec2)
        {
            Vector2 v;

            v = MathHelper.RotateVec2(bulletSpeed, -bulletAngle);
            _reimuCardBulletLayer.AddEntity(new ReimuCardEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                Velocity = v,
                RotateZ = (90 - bulletAngle) * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.6f),
            });

            v = bulletSpeed;
            _reimuCardBulletLayer.AddEntity(new ReimuCardEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                Velocity = v,
                RotateZ = 90 * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.7f),
            });

            v = MathHelper.RotateVec2(bulletSpeed, bulletAngle);
            _reimuCardBulletLayer.AddEntity(new ReimuCardEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                Velocity = v,
                RotateZ = (90 + bulletAngle) * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.6f),
            });
        }
        
        private void Power100Emit(Vector2 posVec2)
        {
            Vector2 v;

            v = MathHelper.RotateVec2(bulletSpeed, -bulletAngle);
            _reimuCardBulletLayer.AddEntity(new ReimuCardEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                Velocity = v,
                RotateZ = (90 - bulletAngle) * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.6f),
            });

            v = bulletSpeed;
            _reimuCardBulletLayer.AddEntity(new ReimuCardEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                Velocity = v,
                RotateZ = 90 * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.7f),
            });

            v = MathHelper.RotateVec2(bulletSpeed, bulletAngle);
            _reimuCardBulletLayer.AddEntity(new ReimuCardEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                Velocity = v,
                RotateZ = (90 + bulletAngle) * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.6f),
            });
            
            v = MathHelper.RotateVec2(bulletSpeed, -20);
            _reimuHomingCardBuletEntityData.AddEntity(new ReimuHomingCardBuletEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                BaseVelocity = v,
                BaseRotation = 70 * Mathf.Deg2Rad,
                Velocity = v,
                RotateZ = 70 * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.6f),
            });
            
            v = MathHelper.RotateVec2(bulletSpeed, 20);
            _reimuHomingCardBuletEntityData.AddEntity(new ReimuHomingCardBuletEntityData()
            {
                Position = posVec2 + v.normalized * 0.4f,
                BaseVelocity = v,
                BaseRotation = 110 * Mathf.Deg2Rad,
                Velocity = v,
                RotateZ = 110 * Mathf.Deg2Rad,
                Color = new Color(1, 1, 1, 0.6f),
            });
        }

        public override void Fire()
        {
            var pos = transform.position;
            var posVec2 = new Vector2(pos.x, pos.y);
            
            if (_lastFireTime + fireInterval < Time.time)
            {
                soundSource.clip = cardEmitSound;
                soundSource.Play();
                
                if (power < 20)
                {
                    Power20Emit(posVec2);
                }
                else if (power < 60)
                {
                    Power60Emit(posVec2);
                }
                else
                {
                    Power100Emit(posVec2);
                }

                _lastFireTime = Time.time;
            }
        }

        public override void OnHit()
        {
            if (godMode)
                return;

            if (!_isDead && Time.time - _lastDeathTime > godTime)
            {
                StartCoroutine(DeadCoroutine());
            }
        }

        private IEnumerator DeadCoroutine()
        {
            _isDead = true;
            
            EntityRenderFeature.EntityColorOverride = Color.red;
            // EntitySubLayer.GlobalWorkingState = false;

            soundSource.clip = deathSound;
            soundSource.Play();
            
            var ring = Instantiate(deadRingPrefab, transform);
            ring.transform.position = transform.position;

            Time.timeScale = 0f;

            DanmakuScenario.BulletDeathZone.w = 1;
            
            yield return StartCoroutine(RaisingBulletDeathZone(
                transform.position.x, transform.position.y, 15f, 1f));
            
            DanmakuScenario.BulletDeathZone.w = 0;

            power = 1;
            
            Time.timeScale = 1f;
            EntityRenderFeature.EntityColorOverride = Color.white;
            
            Destroy(ring);
            
            _lastDeathTime = Time.time;
            RecordPlayerDeath();
            
            _isDead = false;
        }

        public override void OnEnterMonsterState()
        {
            if (_isDead)
                return;

            collidePoint.SetActive(true);
            _animator.SetBool("Darken", true);
            
            _state = State.Monster;
        }

        public override void OnLeaveMonsterState()
        {
            collidePoint.SetActive(false);
            _animator.SetBool("Darken", false);
            
            _state = State.Human;
        }
    }
}